package com.shelpe.services.keywords.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.shelpe.services.keywords.controller.EffectableKeywordDto;
import com.shelpe.services.keywords.controller.SearchCriteria;
import com.shelpe.services.keywords.entity.jpa.Adgroup;
import com.shelpe.services.keywords.entity.jpa.Campaign;
import com.shelpe.services.keywords.entity.jpa.OnlineStatus;
import com.shelpe.services.keywords.model.KeywordEffectExample;
import com.shelpe.services.keywords.model.RptKeywordDto;
import com.shelpe.services.keywords.readdao.ReadRptKeywordMapper;
import com.shelpe.services.keywords.repository.jpa.AdgroupRepository;
import com.shelpe.services.keywords.repository.jpa.CampaignRepository;
import com.shelpe.services.keywords.utils.CriteriaUtils;

import lombok.Data;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
@Setter
public class OopKeywordService {

	@Autowired
	private ReadRptKeywordMapper rptKeywordMapper;
	@Autowired
	private AdgroupRepository adgroupRepository;
	@Autowired
	private CampaignRepository campaignRepository;

	@Data
	public static class SearchSettings {
		private boolean onlineAdgroup;
		private List<SearchCriteria> criterias;
	}

	public List<EffectableKeywordDto> findKeywords(long userID, List<Long> adgroupIDs, List<Long> campaignIDs,
			String device, int days, SearchSettings settings) {
		List<EffectableKeywordDto> rets = new ArrayList<EffectableKeywordDto>();
		long start = System.currentTimeMillis();

		// 分解成推广组来查询
		List<Adgroup> adgroups = new ArrayList<Adgroup>();
		if (adgroupIDs != null && adgroupIDs.size() > 0) {
			adgroups.addAll(this.adgroupRepository.findByAutoIDIn(adgroupIDs));
		}
		if (campaignIDs != null && campaignIDs.size() > 0) {
			if (settings.onlineAdgroup) {// 如果需要推广中的推广组，可以通过推广中推广计划来过滤一些无用的
				List<Campaign> campaigns = this.campaignRepository.findByAutoIDIn(campaignIDs);
				for (Campaign cam : campaigns) {
					if (cam.getOnlineStatus() != OnlineStatus.online) {
						campaignIDs.remove(cam.getAutoID());
					}
				}
			}
			if (campaignIDs.size() > 0) {
				adgroups.addAll(this.adgroupRepository.findByCampaignIDIn(campaignIDs));
			}
		}

		// 得到符合的推广组编号
		List<Long> selectedAdgroupIDs = new ArrayList<Long>();
		for (Adgroup ad : adgroups) {
			boolean canAdd = true;
			if (settings.onlineAdgroup) {
				canAdd = (ad.getOnlineStatus() == OnlineStatus.online) && ad.getOfflineType() == OnlineStatus.online;
			}
			if (canAdd) {
				selectedAdgroupIDs.add(ad.getAutoID());
			}
		}
		log.info("findKeywords - query keyword with adgroupIDs: {}", selectedAdgroupIDs);
		if (selectedAdgroupIDs.size() == 0) {
			return rets;
		}

		KeywordEffectExample rptExample = new KeywordEffectExample();
		rptExample.setUserId(userID);
		KeywordEffectExample.Criteria rptCriteria = this.buildRptKeywordExampleCriteria(rptExample, days, device);
		rptCriteria.andAdgroupIdIn(selectedAdgroupIDs);
		// 如果设置了查询条件，需要根据报表数据解决查询
		if (settings.getCriterias() != null && settings.getCriterias().size() > 0) {
			log.debug("Criterias {}", settings.getCriterias());
			if (settings.getCriterias() != null) {
				KeywordEffectExample.Criteria rptHavingCriteria = rptExample.createHavingCriteria();
				for (SearchCriteria sc : settings.getCriterias()) {
					CriteriaUtils.toCriteria(rptHavingCriteria, sc);
				}
			}
		}
		log.debug("rptExample {}", rptExample);
		
		//根据条件联合查询返回所需要的数据
		List<RptKeywordDto> rptKeywords = this.rptKeywordMapper.selectByExampleFromKeywordAndRpt(rptExample);
		for (RptKeywordDto kw : rptKeywords) {
			EffectableKeywordDto dto = new EffectableKeywordDto();
			dto.fromRptKeywordDto(kw);
			rets.add(dto);
		}

		
		log.info("findKeywords cost {} ms: userID({}) - campaignIDs({}) - adgroupIDs({})",
				System.currentTimeMillis() - start, userID, campaignIDs, adgroupIDs);
		return rets;
	}

	private KeywordEffectExample.Criteria buildRptKeywordExampleCriteria(KeywordEffectExample example, int days,
			String device) {
		KeywordEffectExample.Criteria criteria = example.createCriteria();
		Date yesterday = DateUtils.addDays(DateUtils.truncate(new Date(), Calendar.DATE), -1);
		criteria.andDateBetween(DateUtils.addDays(yesterday, 1 - days), yesterday);

		if ("mobile".equals(device)) {
			criteria.andSourceBetween((byte) 4, (byte) 5);
		} else {
			criteria.andSourceBetween((byte) 1, (byte) 2);
		}
		return criteria;
	}
}
